package com.server.common.logistics.postal;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.google.gson.reflect.TypeToken;
import com.server.common.code.utils.GsonUtils;
import com.server.common.logistics.base.BaseLogisticsService;
import com.server.common.logistics.enums.ApiEnum;
import com.server.common.logistics.enums.LogisticsCompanyEnum;
import com.server.common.logistics.postal.create.PostalCreateOrderRequest;
import com.server.common.logistics.postal.create.PostalCreateOrderResponse;
import com.server.common.logistics.postal.enums.PostalApiEnum;
import com.server.common.logistics.postal.printLabel.PostalPrintfLabelRequest;
import com.server.common.logistics.postal.printLabel.PostalPrintfLabelResponse;
import com.server.common.logistics.postal.token.PostalTokenRequest;
import com.server.common.logistics.postal.token.PostalTokenResponse;
import com.server.common.logistics.postal.track.PostalGetTrackingRequest;
import com.server.common.logistics.postal.track.PostalGetTrackingResponse;
import com.server.common.logistics.request.LogisticsRequest;
import com.server.common.logistics.result.CreateOrderResult;
import com.server.common.logistics.result.GetTrackResult;
import com.server.common.logistics.result.PrintLabelSyncResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

@Component
@Slf4j
public class PostalServiceImpl extends BaseLogisticsService {

    @Resource
    private PostalConfig postalConfig;

    //region 变量
    //token
    private static String token = "";

    //时效 ms 1000ms * 60 * 30 = 30分钟  30分钟 *3 = 1时30分钟
    private final static Long time = 1000 * 60 * 30L * 3;

    //旧时间
    private static Date oldDate = null;

    //返回成功
    private final static String OK = "OK";
    //endregion

    @Override
    public LogisticsCompanyEnum getLogisticsCompanyEnum() {
        return LogisticsCompanyEnum.POSTAL;
    }

    //region 获取Token
    /**
     * 获取Token-应放redis
     * @author LXC
     * @date 2022-07-18 16:14
     */
    private String getToken(){
        if(!ObjectUtils.isEmpty(token)){
            return token;
        }

        if(!ObjectUtils.isEmpty(oldDate)){
            return token;
        }

        if(DateUtil.betweenMs(oldDate,DateUtil.date()) <= time){
            return token;
        }

        HttpRequest post = HttpUtil.createPost(postalConfig.getUrl() + PostalApiEnum.GET_TOKEN.getApiPath());
        PostalTokenRequest postalTokenRequest = new PostalTokenRequest();
        postalTokenRequest.setClient(postalConfig.getClient());
        postalTokenRequest.setUn(postalConfig.getUserCode());
        postalTokenRequest.setPw(postalConfig.getPassWord());
        postalTokenRequest.setRefresh(false);
        post.body(GsonUtils.getGson().toJson(postalTokenRequest));
        try {
            String body = post.execute().body();
            log.error("邮政返回Token接口:"+body);

            PostalResponse<PostalTokenResponse> postalResponse = GsonUtils.getGson().fromJson(body,new TypeToken<PostalTokenResponse>(){}.getType());

            if(OK.equals(postalResponse.getCode())){
                token = postalResponse.getData().getToken();
                oldDate = DateUtil.date();
                return token;
            }
        }catch (Exception e){
            log.error("获取token失败",e);
        }

        return "";
    }
    //endregion

    @Override
    public   <T> PostalResponse<T> baseRequest(ApiEnum apiEnum, Object params){

        HttpRequest request = HttpUtil.createPost(postalConfig.getUrl() +apiEnum.getApiPath());
        //添加请求头
        request.header("X-Auth-Token", getToken());
        request.header("Content-Type", ContentType.JSON.getValue());

        //添加body
        String param = GsonUtils.getGson().toJson(params);
        log.error("邮政参数接口:"+param);
        request.body(param);

        String body = request.execute().body();
        log.error("邮政返回接口:"+body);

        return GsonUtils.getGson().fromJson(body,new TypeToken<PostalResponse<T>>(){}.getType());
    }

    @Override
    public CreateOrderResult createOrder(LogisticsRequest orderRequest) {
        CreateOrderResult createOrderResult = new CreateOrderResult();

        try {

            if(!(orderRequest instanceof PostalCreateOrderRequest)){
                createOrderResult.setErrorMsg("创建物流订单参数有误");
                return createOrderResult;
            }

            PostalCreateOrderRequest postalCreateOrderRequest = (PostalCreateOrderRequest) orderRequest;
            postalCreateOrderRequest.setUserCode(postalConfig.getUserCode());
            PostalResponse<PostalCreateOrderResponse> postalResponse = baseRequest(PostalApiEnum.CREATE_ORDER, orderRequest);

            if(!postalResponse.responseOk()){
                createOrderResult.setErrorMsg(postalResponse.getMsg());
                return createOrderResult;
            }

            if(postalResponse.dataEmpty()){
                createOrderResult.setErrorMsg("创建物流订单失败");
                return createOrderResult;
            }

            PostalCreateOrderResponse data = postalResponse.getData();
            createOrderResult.setTrackingNumber(data.getTrackingNumber());

        }catch (Exception e){
            log.error("创建物流订单失败",e);
            createOrderResult.setErrorMsg("创建物流订单失败");
        }

        createOrderResult.setErrorMsg("创建物流订单参数有误");
        return createOrderResult;
    }

    @Override
    public PrintLabelSyncResult printLabelSync(LogisticsRequest printLabelSyncRequest) {
        PrintLabelSyncResult printLabelSyncResult = new PrintLabelSyncResult();

        try {
            if(!(printLabelSyncRequest instanceof PostalPrintfLabelRequest)){
                printLabelSyncResult.setErrorMsg("打印面单参数有误");
                return printLabelSyncResult;
            }
            PostalPrintfLabelRequest postalPrintfLabelRequest = (PostalPrintfLabelRequest) printLabelSyncRequest;
            postalPrintfLabelRequest.setUserCode(postalConfig.getUserCode());

            PostalResponse<PostalPrintfLabelResponse> postalResponse= baseRequest(PostalApiEnum.PRINT_LABEL, printLabelSyncRequest);

            if(!postalResponse.responseOk()){
                printLabelSyncResult.setErrorMsg(postalResponse.getMsg());
                return printLabelSyncResult;
            }

            if(postalResponse.dataEmpty()){
                printLabelSyncResult.setErrorMsg("打印面单失败");
                return printLabelSyncResult;
            }
            PostalPrintfLabelResponse data = postalResponse.getData();
            byte[] bytes = Base64.decode(data.getLabel());
            printLabelSyncResult.setBytes(bytes);
        }catch (Exception e){
            log.error("打印面单失败",e);
            printLabelSyncResult.setErrorMsg("打印面单失败");
        }

        return printLabelSyncResult;
    }

    @Override
    public GetTrackResult getTracking(LogisticsRequest getTrackRequest) {
        GetTrackResult getTrackResult = new GetTrackResult();

        try {
            if(!(getTrackRequest instanceof PostalGetTrackingRequest)){
                getTrackResult.setErrorMsg("获取物流轨迹参数有误");
                return getTrackResult;
            }

            PostalGetTrackingRequest postalGetTrackingRequest = (PostalGetTrackingRequest) getTrackRequest;
            postalGetTrackingRequest.setUserCode(postalConfig.getUserCode());

            PostalResponse<PostalGetTrackingResponse> postalResponse = baseRequest(PostalApiEnum.GET_TRACK, getTrackRequest);

            if(!postalResponse.responseOk()){
                getTrackResult.setErrorMsg(postalResponse.getMsg());
                return getTrackResult;
            }

            if(postalResponse.dataEmpty()){
                getTrackResult.setErrorMsg("获取物流轨迹失败");
                return getTrackResult;
            }
            PostalGetTrackingResponse data = postalResponse.getData();
            if(ObjectUtils.isEmpty(data)){
                getTrackResult.setTackList(new ArrayList<>());
                return getTrackResult;
            }
            List<PostalGetTrackingResponse.Tack> tackList = data.getTackList();

            //起始时间
            PostalGetTrackingResponse.Tack startTack = CollUtil.getFirst(tackList);
            //最后一个物流时间
            PostalGetTrackingResponse.Tack overTack = CollUtil.getLast(tackList);
            //运输时间
            long transitDay = DateUtil.between(DateUtil.parseDate(startTack.getDatetime()), DateUtil.parseDate(overTack.getDatetime()),DateUnit.DAY);
            getTrackResult.setTransitDay((int) Math.max(transitDay,0));

            //停留时间
            long stayDay = DateUtil.between(DateUtil.parseDate(overTack.getDatetime()), DateUtil.date(),DateUnit.DAY);
            getTrackResult.setStayDay((int) Math.max(stayDay,0));

            //
            for (PostalGetTrackingResponse.Tack tracking :tackList){
                GetTrackResult.Tack tack = new GetTrackResult.Tack();
                tack.setTime(tracking.getDatetime());
                tack.setContent(tracking.getInfo());
                tack.setLocation(tracking.getLocation());
                tack.setStatusCode(tracking.getStatus());
                tack.setStatusName(tracking.getChinaPostTrace());
                getTrackResult.getTackList().add(tack);
            }
        }catch (Exception e){
            log.error("获取物流轨迹失败",e);
            getTrackResult.setErrorMsg("获取物流轨迹失败");
        }

        getTrackResult.setErrorMsg("获取物流轨迹参数有误");
        return getTrackResult;
    }
}
